package com.wh.springboot.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wh.springboot.common.Result;
import com.wh.springboot.common.entity.Files;
import com.wh.springboot.mapper.FileMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;


@RestController
/**
 * 文件上传接口
 * @param  file 前端传递过来的文件
 * @return
 * @throw IOException
 */
@RequestMapping("/file")
public class FileController {
    //通过这个注解，将文件存放磁盘路径引入进来
//    @Value("${files.upload.path}")
    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Value("${server.ip}")
    private String serverIp;
    @Resource
    private FileMapper fileMapper;

    //上传
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {

        String originalFilename = file.getOriginalFilename();//获取原始名称
        String type = FileUtil.extName(originalFilename);//获取文件类型
        long size = file.getSize();//获取文件大小

        //定义一个文件唯一的标识码
        String uuid = IdUtil.fastSimpleUUID();
        String fileUUid = uuid + StrUtil.DOT + type;

        //实际存储的file
        //StrUtil.DOT 是点
        File uploadFile = new File(fileUploadPath + fileUUid);
        //判断配置文件的父级目录是否存在，若不存在，则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }


        String url;
        //上传文件到磁盘
        //把获取到的文件存储到磁盘目录
        file.transferTo(uploadFile);
        // 获取文件 md5 通过对比md5避免重复上传相同内容的文件
        //获取文件的md5
        String md5 = SecureUtil.md5(uploadFile);

        //从数据库查询是否存在相同的记录
        Files files = getFileByMd5(md5);
        if (files != null) { //若有相同记录
            url = files.getUrl();//获取url
            uploadFile.delete();//由于文件已经存在，所以删除刚才上传的重复文件

        } else {//数据库若不存在重复文件，则不删除刚才上传的文件
            url = "http://" + serverIp + ":9090/file/" + fileUUid;
        }


        // 存储数据库
        //URL 把下载需要的参数都加上
        Files saveFile = new Files();
        saveFile.setName(originalFilename); //设置文件名
        saveFile.setType(type);//设置类型
        saveFile.setSize(size / 1024);//设置文件大小
        saveFile.setUrl(url);
        saveFile.setMd5(md5);
        fileMapper.insert(saveFile);//插入到数据库
        return url;
    }

    /**
     * 文件下载路径 http://localhost:9090/file/{fileUUid}
     *
     * @param fileUUid
     * @param response
     * @throws IOException
     */
    // 下载
    @GetMapping("/{fileUUid}")
    //  @PathVariable接收传过来的路径标识位
    public void download(@PathVariable String fileUUid, HttpServletResponse response) throws IOException {
        //下载路径 fileUUid = uuid + StrUtil.DOT + type;
        // 根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUid);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUid, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * 通过文件的md5查询文件
     *
     * @param md5
     * @return
     */
    //    封装一个方法，针对md5
    private Files getFileByMd5(String md5) {
        //获取文件的MD5
        //查询文件的md5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        List<Files> filesList = fileMapper.selectList(queryWrapper);
        //判断list为空 返回 null ，不为空就获取到第一个
        return filesList.size() == 0 ? null : filesList.get(0);
    }

    /**
     * 分页查询接口
     * 接口路径:/file/page
     * *@RequestParam接收* ?pageNum=1&pageSize=10
     *
     * @param pageNum
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public Result findPage(@RequestParam Integer pageNum,
                           @RequestParam Integer pageSize,
                           @RequestParam(defaultValue = "") String name) {
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        //查询未删除记录
        queryWrapper.eq("is_delete", false);
        //降序
        queryWrapper.orderByDesc("id");

        //输入的值是非空的话，再执行
        if (!"".equals(name)) {
            queryWrapper.like("name", name);
        }
        IPage<Files> p = new Page<>(pageNum, pageSize);
        return Result.success(fileMapper.selectPage(p, queryWrapper));
    }

    /**
     * 删除数据
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")//id 与下面的id必须一致
    //    @PathVariable 表示 url 这个参数
    public Result delete(@PathVariable Integer id) {
        //简单查询id
        Files files = fileMapper.selectById(id);
        //#isdelet字段等于true
        files.setIsDelete(true);
        fileMapper.updateById(files);
        return Result.success();
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/del/batch")
    public Result deleteBatch(@RequestBody List<Integer> ids) {
        //select * from sys_file where id in(id,id,id...)
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", ids);
        List<Files> files = fileMapper.selectList(queryWrapper);
        for (Files file : files) {
            file.setIsDelete(true);
            fileMapper.updateById(file);

        }
        return Result.success();
    }

    /**
     * 更新一个字段
     *
     * @param files
     * @return
     */
    // 新增和修改
    @PostMapping("/update")
    public Result save(@RequestBody Files files) {
        //新增或者更新
        return Result.success(fileMapper.updateById(files));
    }


}
